home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Ham Radio 2000
/
Ham Radio 2000.iso
/
ham2000
/
packet
/
tf27bsrc
/
cruntime.mac
< prev
next >
Wrap
Text File
|
1994-07-04
|
60KB
|
1,478 lines
; ***********************************************************************
; * *
; * *
; * ***** ***** *
; * ***** ***** *
; * ***** ***** *
; * ***** ***** *
; * ***** ***** *
; * ***** ***** *
; * ***** ***** *
; * ***** ***** The Firmware. The Net. *
; * ***** ***** Portable. Compatible. *
; * ***** ***** Public Domain. *
; * ***** ***** By NORD><LINK. *
; * *
; * *
; * *
; * CRUNTIME.MAC - Z80 C Runtime Library *
; * (modifizierte Version des Runtime-Moduls *
; * aus dem Q/C-Compilerpaket) *
; * *
; * *
; * angelegt: DC4OX *
; * modifiziert: *
; * *
; ***********************************************************************
.z80
; =======================================================================
;
; Namen mit '?' als erstem Zeichen sind die Namen, die der Compiler
; benutzt. Sonstige Namen sind als Aequivalenzen zu den ?-Namen zur
; vereinfachten Bearbeitung des vom Compiler stammenden Assembler-
; Sources vorgesehen.
;
; Fuer die Aufrufe mit Parametern siehe auch MAKROS.MAC.
;
;
; * (RST38) ?loc local Parameter hinter Aufruf (8 Bit) :
;
; 00offset LD HL,(BC+offset)
; 01offset LD (BC+offset),HL
; 10offset LD (BC+offset),0000h Word
; 11offset LD (BC+offset),00h Byte
;
;
; * (RST30) ?addhl addhl HL := HL + 8-Bit-Parameter (hinter Aufruf)
; * ?Aeq0 Aeq0 HL := (A == 0)
; ?gcf lHiBx HL := LSB (BC) sign extension
; ?gc lHiHx HL := LSB (HL) sign extension
; (RST10) ?sxt lHAx HL := A sign extension
; * ?gcsi lDiiHx DE := LSB ((HL)) sign extension
; ?gcs lDiHx DE := LSB (HL) sign extension
; (RST18) ?gf lHiB HL := (BC)
; (RST20) ?g lHiH HL := (HL)
; ?gs lDiH DE := (HL)
; * (RST08) ?inc incwiH (HL) := (HL) + 1, 16 Bit, HL := HL + 1
; * ?dec decwiH (HL) := (HL) - 1, 16 Bit, HL := HL - 1
; ?p liDH (DE) := HL
; ?so DorH HL := DE | HL
; ?sx DxorH HL := DE ^ HL
; ?sa DandH HL := DE & HL
; * ?sec DeqAx HL := DE == A sign extended
; ?se DeqH HL := DE == HL
; ?sne DneH HL := DE != HL
; ?sgt DgtHs HL := DE > HL signed
; ?ugt DgtHu HL := DE > HL unsigned
; ?slt DltHs HL := DE < HL signed
; ?ult DltHu HL := DE < HL unsigned
; ?sle DleHs HL := DE <= HL signed
; ?ule DleHu HL := DE <= HL unsigned
; ?sge DgeHs HL := DE >= HL signed
; ?uge DgeHu HL := DE >= HL unsigned
; ?ssr DsrHa HL := DE >> HL arithmetic
; ?s1sr HsrDa HL := HL >> DE arithmetic
; ?ssl DslH HL := DE << HL
; ?s1sl HslD HL := HL << DE
; ?usr DsrHl HL := DE >> HL logic
; ?u1sr HsrDl HL := HL >> DE logic
; ?ss DminH HL := DE - HL
; ?s1s HminD HL := HL - DE
; ?sneg com2H HL := -HL
; ?scom com1H HL := ~HL
; ?sna nDandH HL := !(DE & HL)
; (RST28) ?sn nH HL := !HL
; ?smult DmulH HL := DE * HL
; ?umult " "
; ?sdiv DdivHs HL := DE / HL, signed
; ?s1div HdivDs HL := HL / DE, signed
; ?udiv DdivHu HL := DE / HL, unsigned
; ?u1div HdivDu HL := HL / DE, unsigned
; ?srem DmodHs HL := DE % HL, signed
; ?s1rem HmodDs HL := HL % DE, signed
; ?urem DmodHu HL := DE % HL, unsigned
; ?u1rem HmodDu HL := HL % DE, unsigned
;
;
; ?sw switch switch-Anwahl, HL enthaelt zu testenden
; Wert, Tabelle als Parameter hinter
; Aufruf :
;
; 16 Bit Anzahl Faelle ohne default
; je Fall : 16 Bit Fall-Wert
; 16 Bit Adresse des Falls
; .
; .
; 16 Bit Adresse default Bearbeitung
;
;
; ?en fentp function entry for parameter,
; es werden die Stackframepointer
; (BC/IX) gesetzt, so dass auf
; Funktionsargumente zugegriffen werden kann
;
; ?ens fentpl function entry for parameter/locals,
; wie fentp, zusaetzlich wird Platz fuer
; lokale Variable auf dem Stack
; geschaffen, Platz in Bytes negativ als
; Parameter hinter Aufruf (16 Bit)
;
; ?exs fextpl function exit for parameter/locals,
; nach fentpl, der lokal benoetigte
; Platz wird zurueckgegeben, Platz in
; Bytes positiv als Parameter hinter
; Aufruf (16 Bit)
;
;
; * -> zusaetzlich zum originalen Runtime-Modul
;
;
; Zeichenerklaerung ?-Namen :
;
; s am Namensanfang steht fuer "short" in Unterscheidung zu der
; long-Library
;
; u am Namensanfang steht fuer den unsigned-Typ
;
; g = get HL primary register
; gs = get secondary DE secondary register
; gc = get character BC stack frame pointer
; gf = get from frame
; p = put
;
;
; Zeichenerklaerung Aequivalente :
;
; B = BC or = logisches Oder
; D = DE xor = logisches Exklusiv-Oder
; H = HL and = logisches Und
; A = A eq = equal, ==
; l = load (1. Zeichen) ne = not equal, !=
; logic sonst gt = greater than, >
; u = unsigned lt = less than, <
; s = signed le = less equal, <=
; a = arithmetic ge = greater equal, >=
; x = sign extend, Byte -> Word sr = shift right, >>
; i = indirect (reg) sl = shift left, <<
; incw = increment word, ++ min = minus, -
; decw = decrement word, -- com1 = Einerkomplement, ~
; n = not, ! com2 = Zweierkomplement, -
; mul = multiply, *
; div = divide, /
; mod = modulo, %
;
; =======================================================================
; +---------------------------------------------------------------------+
; | |
; | (RST38) Zugriffe auf Funktionsparameter und lokale Variable sowie |
; | Loeschen lokaler Variable. |
; | |
; | 8-Bit-Parameter hinter Aufruf : |
; | |
; | 00offset - LD HL,(BC+offset) offset maximal 64 ! |
; | 01offset - LD (BC+offset),HL |
; | 10offset - LD (BC+offset),0000h Word |
; | 11offset - LD (BC+offset),00h Byte |
; | |
; | A benutzt. |
; | |
; +---------------------------------------------------------------------+
public local
public ?loc
local:
?loc: ex (SP),HL ; 8-Bit-Parameter vom Stack holen
ld A,(HL)
inc HL ; Returnadresse ein Byte weiter
ex (SP),HL
bit 7,A ; 1xxxxxxx ?
jr NZ,?loc2 ; ja -
bit 6,A ; nein - 01xxxxxx ?
jr NZ,?loc1 ; ja -
;
; 00xxxxxx : LD HL,(BC+xxxxxx)
;
ld L,A ; nein - HL = Offset
ld H,0
add HL,BC ; + BC
ld A,(HL) ; LSB holen
inc HL ; Zeiger auf MSB
ld H,(HL) ; MSB holen
ld L,A ; HL = MSBLSB
ret ; das war's
;
; 01xxxxxx : LD (BC+xxxxxx),HL
;
?loc1: push DE ; benutztes Register sichern
ex DE,HL ; HL merken
and 00111111b ; Offset maskieren
ld L,A ; HL = Offset
ld H,0
add HL,BC ; + BC
ld (HL),E ; LSB schreiben
inc HL ; Zeiger auf MSB-Stelle
ld (HL),D ; MSB schreiben
ex DE,HL ; HL restaurieren
pop DE ; benutztes Register restaurieren
ret ; das war's
?loc2: bit 6,A ; 11xxxxxx ?
jr NZ,?loc3 ; ja -
;
; 10xxxxxx : LD (BC+xxxxxx),0000h
;
push HL ; nein - benutztes Register sichern
and 00111111b ; Offset maskieren
ld L,A ; HL = Offset
ld H,0
add HL,BC ; + BC
ld (HL),00h ; LSB loeschen
inc HL ; Zeiger auf MSB-Stelle
ld (HL),00h ; MSB loeschen
pop HL ; benutztes Register restaurieren
ret ; das war's
;
; 11xxxxxx : LD (BC+xxxxxx),00h
;
?loc3: push HL ; benutztes Register sichern
and 00111111b ; Offset maskieren
ld L,A ; HL = Offset
ld H,0
add HL,BC ; + BC
ld (HL),00h ; Byte loeschen
pop HL ; benutztes Register restaurieren
ret ; das war's
; +---------------------------------------------------------------------+
; | |
; | (RST30) Offset auf HL addieren, 8-Bit-Offset hinter Aufruf. |
; | |
; | DE benutzt. |
; | |
; +---------------------------------------------------------------------+
public addhl
public ?addhl
addhl:
?addhl: ex (SP),HL ; 8-Bit-Parameter vom Stack holen, HL sichern
ld E,(HL)
ld D,0
inc HL ; Returnadresse ein Byte weiter
ex (SP),HL ; Returnaddresse auf Stack, HL wieder setzen
add HL,DE ; Offset addieren
ret ; das war's
; +--------------------------------------------------------------------+
; | |
; | Teste A auf 0. |
; | |
; | A == 0 -> HL = 1 (TRUE) |
; | A != 0 -> HL = 0 (FALSE) |
; | |
; | A benutzt. |
; | |
; +--------------------------------------------------------------------+
public Aeq0
public ?Aeq0
Aeq0:
?Aeq0: or A ; A == 0 ?
jr Z,?Aeq0a ; ja - HL = TRUE (1)
xor A ; nein - HL = FALSE (0)
jr ?Aeq0b
?Aeq0a: inc A
?Aeq0b: ld L,A
ld H,0
ret ; das war's
; +---------------------------------------------------------------------+
; | |
; | HL indirekt Laden mit Byte an BC, Sign Extension HL := LSB (BC) |
; | |
; | A benutzt. |
; | |
; +---------------------------------------------------------------------+
public lHiBx
public ?gcf
lHiBx:
?gcf: ld L,C ; fuer HL = LSB (HL) sign extension, s.u.
ld H,B
; +---------------------------------------------------------------------+
; | |
; | HL indirekt laden mit Byte an (HL), Sign extension, |
; | HL := LSB (HL). |
; | |
; | A benutzt. |
; | |
; +---------------------------------------------------------------------+
public lHiHx
public ?gc
lHiHx:
?gc: LD A,(HL) ; fuer HL := A sign extension, s.u.
; +---------------------------------------------------------------------+
; | |
; | (RST10) HL laden mit A, Sign Extension. |
; | |
; | A benutzt. |
; | |
; +---------------------------------------------------------------------+
public lHAx
public ?sxt
lHAx:
?sxt: ld L,A ; LSB setzen
rlca ; Bit 8 = Vorzeichen = Carry
sbc A,A ; A - A - Carry -> FF wenn negativ, sonst 0
ld H,A ; MSB setzen
ret ; das war's
; +---------------------------------------------------------------------+
; | |
; | DE laden mit Byte an Adresse an (HL), Sign Extension. |
; | |
; | A benutzt. |
; | |
; +---------------------------------------------------------------------+
public lDiiHx
public ?gcsi
lDiiHx:
?gcsi: call ?g ; Adresse an (HL) fuer ?gcs (s.u.) holen
; +---------------------------------------------------------------------+
; | |
; | DE laden mit Byte an (HL), Sign Extension. |
; | |
; | A benutzt. |
; | |
; +---------------------------------------------------------------------+
public lDiHx
public ?gcs
lDiHx:
?gcs: ld A,(HL) ; Byte an HL holen
ld E,A ; LSB setzen
rlca ; Bit 8 = Vorzeichen = Carry
sbc A,A ; A - A - Carry -> FF wenn negativ, sonst 0
ld D,A ; MSB setzen
ret ; das war's
; +---------------------------------------------------------------------+
; | |
; | (RST18) HL laden mit 16-Bit-Wort an (BC). |
; | |
; | A benutzt. |
; | |
; +---------------------------------------------------------------------+
public lHiB
public ?gf
lHiB:
?gf: ld L,C ; HL := BC fuer ?g (s.u.)
ld H,B
; +---------------------------------------------------------------------+
; | |
; | (RST20) HL laden mit 16-Bit-Wort an (HL). |
; | |
; | A benutzt. |
; | |
; +---------------------------------------------------------------------+
public lHiH
public ?g
lHiH:
?g: ld A,(HL) ; LSB holen
inc HL ; Zeiger auf MSB
ld H,(HL) ; MSB holen
ld L,A ; LSB setzen
ret ; das war's
; +---------------------------------------------------------------------+
; | |
; | DE laden mit 16-Bit-Wort an (HL), HL := HL + 1. |
; | |
; +---------------------------------------------------------------------+
public lDiH
public ?gs
lDiH:
?gs: ld E,(HL) ; LSB holen
inc HL ; Zeiger auf MSB
ld D,(HL) ; MSB holen
ret ; das war's
; +---------------------------------------------------------------------+
; | |
; | (RST08) 16-Bit-Wort an (HL) um 1 erhoehen, HL := HL + 1. |
; | |
; | A, DE benuzt. |
; | |
; +---------------------------------------------------------------------+
public incwiH
public ?inc
incwiH:
?inc: push HL ; Adresse sichern
call ?g ; LD HL,(HL) - Inhalt holen
inc HL ; + 1
pop DE ; Adresse holen
jr ?p ; LD (DE),HL - Inhalt zurueck
; +---------------------------------------------------------------------+
; | |
; | 16-Bit-Wort an (HL) um 1 erniedrigen, HL := HL - 1. |
; | |
; | A, DE benutzt. |
; | |
; +---------------------------------------------------------------------+
public decwiH
public ?dec
decwiH:
?dec: push HL ; Adresse sichern
call ?g ; LD HL,(HL) - Inhalt holen
dec HL ; - 1
pop DE ; Adresse holen - dann ?p (s.u.)
; +---------------------------------------------------------------------+
; | |
; | Inhalt von HL an (DE) schreiben, DE := DE + 1. |
; | |
; | A benutzt. |
; | |
; +---------------------------------------------------------------------+
public liDH
public ?p
liDH:
?p: ld A,L ; LSB laden
ld (DE),A ; LSB schreiben
inc DE ; Zeiger auf MSB
ld A,H ; MSB laden
ld (DE),A ; MSB schreiben
ret ; das war's
; +---------------------------------------------------------------------+
; | |
; | HL mit DE Oder-verknuepfen, HL := HL | DE. |
; | |
; | A benutzt. |
; | |
; +---------------------------------------------------------------------+
public DorH
public ?so
DorH:
?so: ld A,L ; LSB ...
or E
ld L,A
ld A,H ; MSB ...
or D
ld H,A
ret ; das war's
; +---------------------------------------------------------------------+
; | |
; | HL mit DE Exklusiv-Oder verknuepfen, HL := HL ^ DE. |
; | |
; | A benutzt. |
; | |
; +---------------------------------------------------------------------+
public DxorH
public ?sx
DxorH:
?sx: ld A,L ; LSB ...
xor E
ld L,A
ld A,H ; MSB ...
xor D
ld H,A
ret ; das war's
; +---------------------------------------------------------------------+
; | |
; | HL mit DE Und-verknuepfen, HL := HL & DE. |
; | |
; | A benutzt. |
; | |
; +---------------------------------------------------------------------+
public DandH
public ?sa
DandH:
?sa: ld A,L ; LSB ...
and E
ld L,A
ld A,H ; MSB ...
and D
ld H,A
ret ; das war's
;
; Alle der folgenden Vergleichs-Routinen geben zurueck :
;
; wenn Bedingung wahr = TRUE dann HL = 1 und Z-Flag ist geloescht
; wenn Bedingung falsch = FALSE dann HL = 0 und Z-Flag ist gesetzt
;
; Fuer einen vorzeichenbehafteten Vergleich werden die positiven und
; negativen Zahlen zunaechst so in vorzeichenlose Zahlen gewandelt, dass
; ein vorzeichenloser Vergleich dann das richtige Resultat ergibt.
; Dies Umwandeln geschieht durch Exklusiv-Oder des Vorzeichenbits mit 1 :
;
; -32768 (0x8000) --> 0 (0x0000)
; -32767 (0x8001) --> 1 (0x0001)
; .....
; -1 (0xFFFF) --> 32767 (0x7FFF)
; 0 (0x0000) --> 32768 (0x8000)
; 1 (0x0001) --> 32769 (0x8001)
; .....
; 32766 (0x7FFE) --> 65534 (0xFFFE)
; 32767 (0x7FFF) --> 65535 (0xFFFF)
;
; +---------------------------------------------------------------------+
; | |
; | DE mit A (sign extended) vergleichen, HL := DE == A sign extended. |
; | |
; | TRUE -> HL=1, Z=0 FALSE -> HL=0, Z=1 |
; | |
; | A benutzt. |
; | |
; +---------------------------------------------------------------------+
public DeqAx
public ?sec
DeqAx:
?sec: call ?sxt ; HL = A sign extended fuer ?se (s.u.)
; +---------------------------------------------------------------------+
; | |
; | HL mit DE vergleichen, HL := HL == DE. |
; | |
; | TRUE -> HL=1, Z=0 FALSE -> HL=0, Z=1 |
; | |
; | A benutzt. |
; | |
; +---------------------------------------------------------------------+
public DeqH
public ?se
DeqH:
?se: xor A ; Carry fuer Subtraktion loeschen
sbc HL,DE ; HL := HL - DE
jr Z,?true ; gleich, dann TRUE zurueckgeben
ld H,A ; sonst HL = 0, Z = 0, FALSE setzen
ld L,A
xor A
ret ; das war's
; +---------------------------------------------------------------------+
; | |
; | Ungleich Vergleich, HL := DE != HL. |
; | |
; | TRUE -> HL=1, Z=0 FALSE -> HL=0, Z=1 |
; | |
; | A, DE benutzt. |
; | |
; +---------------------------------------------------------------------+
public DneH
public ?sne
DneH:
?sne: xor A ; Carry fuer Subtraktion loeschen
sbc HL,DE ; HL := HL - DE
ret Z ; gleich, dann war's das, HL := A := 0
ld H,A ; sonst HL := 1, d.h. TRUE
ld L,A
?true: inc L ; das war's
ret
; +---------------------------------------------------------------------+
; | |
; | Groesser als Vergleich, DgtHs : HL := DE > HL vorzeichenbehaftet |
; | DgtHu : HL := DE > HL vorzeichenlos |
; | |
; | TRUE -> HL=1, Z=0 FALSE -> HL=0, Z=1 |
; | |
; | A, DE benutzt. |
; | |
; +---------------------------------------------------------------------+
public DgtHs
public ?sgt
public DgtHu
public ?ugt
DgtHs:
?sgt: ld A,D ; vorzeichenbehaftete Argumente in
xor 80h ; fuer vorzeichenlosen Test
ld D,A ; passende vorzeichenlose Argumente
ld A,H ; wandeln (s.o.)
xor 80h
ld H,A
DgtHu:
?ugt: xor A ; vorzeichenloser Vergleich
sbc HL,DE
ld H,A
ld L,A
jr C,?true
xor A
ret
; +---------------------------------------------------------------------+
; | |
; | Kleiner als Vergleich, DltHs : HL := DE < HL vorzeichenbehaftet |
; | DltHu : HL := DE < HL vorzeichenlos |
; | |
; | TRUE -> HL=1, Z=0 FALSE -> HL=0, Z=1 |
; | |
; | A, DE benutzt. |
; | |
; +---------------------------------------------------------------------+
public DltHs
public ?slt
public DltHu
public ?ult
DltHs:
?slt: ld A,D ; vorzeichenbehaftete Argumente in
xor 80h ; fuer vorzeichenlosen Test
ld D,A ; passende vorzeichenlose Argumente
ld A,H ; wandeln (s.o.)
xor 80h
ld H,A
DltHu:
?ult: ex DE,HL ; vorzeichenloser Vergleich
xor A
sbc HL,DE
ld H,A
ld L,A
jr C,?true
xor A
ret
; +---------------------------------------------------------------------+
; | |
; | Kleiner gleich Vergleich, DleHs : HL := DE <= HL vorzeichenbehaft. |
; | DleHu : HL := DE <= HL vorzeichenlos |
; | |
; | TRUE -> HL=1, Z=0 FALSE -> HL=0, Z=1 |
; | |
; | A, DE benutzt. |
; | |
; +---------------------------------------------------------------------+
public DleHs
public ?sle
public DleHu
public ?ule
DleHs:
?sle: ld A,D ; vorzeichenbehaftete Argumente in
xor 80h ; fuer vorzeichenlosen Test
ld D,A ; passende vorzeichenlose Argumente
ld A,H ; wandeln (s.o.)
xor 80h
ld H,A
DleHu:
?ule: xor A ; vorzeichenloser Vergleich
sbc HL,DE
ld H,A
ld L,A
jr NC,?true
xor A
ret
; +---------------------------------------------------------------------+
; | |
; | Groesser gleich Vergleich, DgeHs : HL := DE >= HL vorzeichenbeh. |
; | DgeHu : HL := DE >= HL vorzeichenlos |
; | |
; | TRUE -> HL=1, Z=0 FALSE -> HL=0, Z=1 |
; | |
; | A, DE benutzt. |
; | |
; +---------------------------------------------------------------------+
public DgeHs
public ?sge
public DgeHu
public ?uge
DgeHs:
?sge: ld A,D ; vorzeichenbehaftete Argumente in
xor 80h ; fuer vorzeichenlosen Test
ld D,A ; passende vorzeichenlose Argumente
ld A,H ; wandeln (s.o.)
xor 80h
ld H,A
DgeHu:
?uge: ex DE,HL ; vorzeichenloser Vergleich
xor A
sbc HL,DE
ld H,A
ld L,A
jr NC,?true
xor A
ret
; +---------------------------------------------------------------------+
; | |
; | Arithmetischen Rechtsschieben, DsrHa : HL := DE >> HL |
; | HsrDa : HL := HL >> DE |
; | |
; +---------------------------------------------------------------------+
public DsrHa
public ?ssr
public HsrDa
public ?s1sr
DsrHa:
?ssr: ex DE,HL ; HL <-> DE
HsrDa:
?s1sr: dec E ; alles geschoben (LSB-Abfrage reicht) ?
ret M ; ja - dann war's das
sra H ; nein - HL arithmetisch rechtsschieben
rr L ; um ein Bit,
jr ?s1sr ; naechstes Bit
; +---------------------------------------------------------------------+
; | |
; | Logisches und arithmetisches Linksschieben, DslH : HL := DE << HL |
; | HslD : HL := HL << DE |
; | |
; +---------------------------------------------------------------------+
public DslH
public ?ssl
public HslD
public ?s1sl
DslH:
?ssl: ex DE,HL ; HL <-> DE
HslD:
?s1sl: dec E ; alles geschoben (LSB-Abfrage reicht) ?
ret M ; ja - dann war's das
add HL,HL ; nein - HL logisch/arithmetisch ein Bit
jr ?s1sl ; linksschieben, naechstes Bit
; +---------------------------------------------------------------------+
; | |
; | Logisches Rechtsschieben, DsrHl : HL := DE >> HL |
; | HsrDl : HL := HL >> DE |
; | |
; +---------------------------------------------------------------------+
public DsrHl
public ?usr
public HsrDl
public ?u1sr
DsrHl:
?usr: ex DE,HL ; HL <-> DE
HsrDl:
?u1sr: dec E ; alles geschoben (LSB Abfrage reicht) ?
ret M ; ja - dann war's das
srl H ; nein - HL logisch rechtsschieben ein Bit
rr L
jr ?u1sr ; naechstes Bit
; +---------------------------------------------------------------------+
; | |
; | Subtraktion vorzeichenlos/vorzeichenbehaftet, |
; | |
; | DminH : HL := DE - HL |
; | HminD : HL := HL - DE |
; | |
; | A benutzt. |
; | |
; +---------------------------------------------------------------------+
public DminH
public ?ss
public HminD
public ?s1s
DminH:
?ss: ex DE,HL ; DE <-> HL
HminD:
?s1s: xor A ; Carry loeschen
sbc HL,DE ; "DE" - "HL"
ret
; +---------------------------------------------------------------------+
; | |
; | Zweierkomplement, HL := -HL. |
; | |
; | A benutzt. |
; | |
; +---------------------------------------------------------------------+
public com2H
public ?sneg
com2H:
?sneg: ld A,H ; HL bitweise invertieren
cpl
ld H,A
ld A,L
cpl
ld L,A
inc HL ; und 1 dazu
ret
; +---------------------------------------------------------------------+
; | |
; | Einerkomplement, HL := ~HL. |
; | |
; | A benutzt. |
; | |
; +---------------------------------------------------------------------+
public com1H
public ?scom
com1H:
?scom: ld A,H ; HL bitweise invertieren
cpl
ld H,A
ld A,L
cpl
ld L,A
ret
; +---------------------------------------------------------------------+
; | |
; | Logisches Und invertiert, HL := !(DE & HL). |
; | |
; | A benutzt. |
; | |
; +---------------------------------------------------------------------+
public nDandH
public ?sna
nDandH:
?sna: call ?sa ; Logisches Und, dann !HL s.u.
; +---------------------------------------------------------------------+
; | |
; | (RST28) Logisches Nicht, HL := !HL. |
; | |
; | A benutzt. |
; | |
; +---------------------------------------------------------------------+
public nH
public ?sn
nH:
?sn: ld A,H ; HL = 0, d.h. FALSE ?
or L
jr Z,?not1
xor A ; nein - Z = 1, d.h. FALSE
ld H,A ; HL = 0, d.h. FALSE
ld L,A
ret ; das war's = return(FALSE)
?not1: inc L ; ja - HL = 1, Z = 0, d.h TRUE
ret ; das war's = return(TRUE)
; +---------------------------------------------------------------------+
; | |
; | Multiplikation, HL := DE * HL vorzeichenbehaftet/vorzeichenlos. |
; | |
; | A, DE benutzt. |
; | |
; +---------------------------------------------------------------------+
public DmulH
public ?smult
public ?umult
DmulH:
?smult:
?umult: ld A,H ; 8 bit * 16 bit oder 16 bit * 16 bit ?
or A
ld A,L ; A LSB Multiplikand (beide Faelle)
ld L,H ; L MSB Multiplikand (16 * 16)
; oder Ergebnisregister HL geloescht (8 * 16)
jr Z,?mult5 ; -> 8 * 16
push BC ; -> 16 * 16, benutztes Register sichern
ld C,H ; MSB Multiplikand sichern
ld HL,0 ; Resultatsregister loeschen
ld B,8 ; 8 Shifts/Additionen fuer LSB
?mult1: srl A ; shifte und
jr NC,?mult2 ; addiere, wenn Bit gesetzt
add HL,DE
?mult2: sla E ; shifte auch Multiplikator
rl D
djnz ?mult1 ; bis alle 8 Bit verarbeitet
ld A,C ; MSB Multiplikand holen
pop BC ; benutztes Register restaurieren
jr ?mult5 ; und nun MSB verarbeiten
?mult3: add HL,DE ; addiere wenn Bit gesetzt
?mult4: sla E ; shifte Multiplikator
rl D
?mult5: srl A ; shifte und
jr C,?mult3 ; addiere wenn Bit gesetzt
jr NZ,?mult4 ; fertig ? -> nein, naechstes Bit
ret ; -> ja, dann war's das
; +---------------------------------------------------------------------+
; | |
; | Division vorzeichenbehaftet, |
; | |
; | DdivHs : HL := DE / HL |
; | HdivDs : HL := HL / DE |
; | |
; | A benutzt. |
; | |
; +---------------------------------------------------------------------+
public HdivDs
public ?s1div
public DdivHs
public ?sdiv
HdivDs:
?s1div: ex DE,HL ; DE <-> HL
DdivHs:
?sdiv: ld A,H ; Vorzeichen des Ergebnisses (Quotient)
xor D ; berechnen
push AF ; und merken
ld A,H ; Divisor negativ ?
or A
jp P,?div1 ; nein -
cpl ; ja - positiv machen (2er-Komplement)
ld H,A
ld A,L
cpl
ld L,A
inc HL
?div1: ld A,D ; Vorzeichen Dividend = Vorzeichen Rest
or A
push AF ; merken
jp P,?div2 ; Dividend negativ ? -> nein -
cpl ; -> ja - positiv machen (2er-Komplement)
ld D,A
ld A,E
cpl
ld E,A
inc DE
?div2: call ?udiv ; vorzeichenlose Division ausfuehren
pop AF ; Rest negativ ?
jp P,?div3 ; nein -
ld A,D ; ja - negativ machen (2er-Komplement)
cpl
ld D,A
ld A,E
cpl
ld E,A
inc DE
?div3: pop AF ; Ergebnis (Quotient) negativ ?
ret P ; nein - dann war's das
ld A,H ; ja - negativ machen (2er-Komplement)
cpl
ld H,A
ld A,L
cpl
ld L,A
inc HL
ret ; das war's
; +---------------------------------------------------------------------+
; | |
; | Division vorzeichenlos, |
; | |
; | DdivHu : HL := DE / HL |
; | HdivDu : HL := HL / DE |
; | |
; | A benutzt. |
; | |
; +---------------------------------------------------------------------+
public HdivDu
public ?u1div
public DdivHu
public ?udiv
HdivDu:
?u1div: ex DE,HL ; DE <-> HL
DdivHu:
?udiv: ld A,H ; Division durch 0 ?
or L
jr NZ,?udiv0
ld E,L ; ja - Ergebnis und Rest 0
ld D,H
ret
?udiv0: push BC ; nein - benutztes Register sichern
ld B,H ; Divisor in BC
ld C,L
ld HL,0 ; Ergebnis (Quotient) loeschen
ld A,16 ; 16 Bit muessen berechnet werden
ex DE,HL ; HL = Dividend
?udiv1: add HL,HL ; Dividend normieren
jr C,?udiv3 ; (linksschieben bis zum Anschlag + 1)
dec A
jr NZ,?udiv1 ; Dividend 0 ? nein - naechstes Bit
pop BC ; ja - benutztes Register restaurieren
ret ; das war's dann schon hier
?udiv2: ex DE,HL ; Ergebnis (Quotient) naechste Stelle
add HL,HL
?udiv3: ex DE,HL ; Dividend naechste Stelle
adc HL,HL
sbc HL,BC ; Dividend - Divisor >= 0 ?
jr NC,?udiv5 ; ja - Ergebnis + 1, naechstes Bit
add HL,BC ; nein - Dividend restaurieren
?udiv4: dec A ; Bitzaehler
jr NZ,?udiv2 ; fertig ? nein - naechstes Bit
ex DE,HL ; ja - HL Quotient, DE Rest
pop BC ; benutztes Reg. restaurieren
ret ; das war's
?udiv5: inc DE ; Ergebnis (Quotient) + 1 und
jr ?udiv4 ; weiter zum naechsten Bit
; +---------------------------------------------------------------------+
; | |
; | Rest vorzeichenbehaftet, |
; | |
; | DmodHs : HL := DE % HL |
; | HmodDs : HL := HL % DE |
; | |
; | A benutzt. |
; | |
; +---------------------------------------------------------------------+
public HmodDs
public ?s1rem
public DmodHs
public ?srem
HmodDs:
?s1rem: ex DE,HL ; DE <-> HL
DmodHs:
?srem: call ?sdiv ; Division ausfuehren
ex DE,HL ; Rest ist Ergebnis
ret
; +---------------------------------------------------------------------+
; | |
; | Rest vorzeichenlos, |
; | |
; | DmodHu : HL := DE % HL |
; | HmodDu : HL := HL % DE |
; | |
; | A benutzt. |
; | |
; +---------------------------------------------------------------------+
public HmodDu
public ?u1rem
public DmodHu
public ?urem
HmodDu:
?u1rem: ex DE,HL ; DE <-> HL
DmodHu:
?urem: call ?udiv ; Division ausfuehren
ex DE,HL ; Rest ist Ergebnis
ret
; +---------------------------------------------------------------------+
; | |
; | switch-Anwahl, HL enthaelt zu testenden Wert, Tabelle als Parameter |
; | hinter Aufruf : |
; | |
; | 16 Bit Anzahl Faelle ohne default ( < 256 ! ) |
; | je Fall : 16 Bit Fall-Wert |
; | 16 Bit Adresse des Falls |
; | . |
; | . |
; | 16 Bit Adresse default Bearbeitung |
; | |
; | A, HL, DE benutzt. |
; | |
; +---------------------------------------------------------------------+
public switch
public ?sw
switch:
?sw: ex DE,HL ; switch-Wert sichern
pop HL ; Adresse der Argumentenliste
push BC ; Stackframe-Pointer sichern
ld C,(HL) ; Anzahl der Faelle
inc HL ; (immer < 256, MSB ignorieren)
?sw1: dec C ; Faelle herunterzaehlen
jp M,?sw3 ; keine weiteren Faelle - default ausfuehren
inc HL ; Fall gefunden (Werte gleich) ?
ld A,(HL) ; LSB ...
cp E
inc HL
jr NZ,?sw2 ; nein - naechster Fall
ld A,(HL) ; MSB ...
cp D
jr Z,?sw3 ; ja - zugehoerige Routine ausfuehren
?sw2: inc HL ; nein - zum naechsten Falleintrag
inc HL
jr ?sw1 ; diesen probieren
?sw3: inc HL ; Adresse des gewaehlten Falls holen
ld A,(HL) ; LSB ...
inc HL
ld H,(HL) ; MSB ...
ld L,A
pop BC ; Stackframe-Pointer restaurieren
jp (HL) ; und Routine ausfuehren
; +---------------------------------------------------------------------+
; | |
; | Funktionsstart fuer Parameter, es werden die Stackframepointer |
; | (BC/IX) gesetzt, so dass auf Funktionsargumente zugegriffen werden |
; | kann. |
; | |
; | Return : HL - benutzt |
; | |
; +---------------------------------------------------------------------+
public fentp
public ?en
fentp:
?en: pop HL ; Returnadresse holen
push BC ; Stackframe-Pointer sichern
ld IX,0 ; lokaler Stackframe-Pointer, kein Platz
add IX,SP ; fuer lokale Variablen benoetigt
push IX ; BC auch Stackframe-Pointer
pop BC
jp (HL) ; das war's - weiter an Returnadresse
; +---------------------------------------------------------------------+
; | |
; | Funktionsstart fuer Parameter/Locals, wie fentp, zusaetzlich wird |
; | Platz fuer lokale Variable auf dem Stack geschaffen, Platz in Bytes |
; | negativ als Parameter hinter Aufruf (16 Bit). |
; | |
; | Return : SP - um angeforderten Platz korrigiert |
; | BC, IX - neuer Stackframe-Pointer |
; | DE, HL - benutzt |
; | |
; | |
; +---------------------------------------------------------------------+
public fentpl
public ?ens
fentpl:
?ens: pop HL ; Adresse Aufrufpar. (angeforderter Platz)
push BC ; Stackframe-Pointer sichern
ld E,(HL) ; LSB angeforderter Platz
inc HL ; Zeiger auf MSB angeforderter Platz
ld D,(HL) ; MSB angeforderter Platz
inc HL ; neue Returnadresse hinter Parameter
ex DE,HL ; Returnadresse <-> angeforderter Platz
add HL,SP ; Stack um angeforderten Platz vermindern
ld SP,HL ; und den Platz reservieren
ld B,H ; lokalen Stackframe-Pointer setzen
ld C,L
push BC ; auch in IX
pop IX
ex DE,HL ; HL = Returnadresse
jp (HL) ; das war's - dort weitermachen
; +---------------------------------------------------------------------+
; | |
; | Funktionsausgang fuer Parameter/Locals, nach fentpl, der lokal |
; | benoetigte Platz wird zurueckgegeben, Platz in Bytes positiv als |
; | Parameter hinter Aufruf (16 Bit). |
; | |
; | Return : SP - um zurueckzugebenden Platz korrigiert |
; | BC, IX - alter Stackframe-Pointer (aufrufende Funktion) |
; | HL - bleibt (Returnwert der Funktion) |
; | A, DE - benutzt |
; | |
; +---------------------------------------------------------------------+
public fextpl
public ?exs
fextpl:
?exs: ex DE,HL ; Returnwert der Funktion sichern
pop HL ; Adresse Aufrufparam. (zurueckzugeb. Platz)
ld A,(HL) ; LSB des zurueckzugebenden Platzes holen
inc HL ; Zeiger auf MSB
ld H,(HL) ; MSB holen
ld L,A ; HL = 16-Bit Anzahl Bytes zureckzugeben
add HL,SP ; = Anzahl Bytes Stack zu korrigieren
ld SP,HL ; lokalen Platz deallokieren
ex DE,HL ; restaurieren des Returnwertes der Funktion
pop BC ; Stackframe-Pointer restaurieren
push BC
pop IX ; sowie Indexregister (auch Stackframe-P.)
ret ; das war's
; +---------------------------------------------------------------------+
; | |
; | Definitionen zum Zusammenspiel mit dem Compiler. |
; | |
; | Bei Benutzung des originalen Compilers werden alle Routinen des |
; | Runtime-Moduls immer als extern deklariert, auch wenn sie nicht |
; | benutzt werden. Bei Benutzung eines anderen Runtime-Moduls mit |
; | weniger Routinen muessen die fehlenden Routinen also zumindest |
; | definiert werden. |
; | |
; +---------------------------------------------------------------------+
public ?enr
public ?ensr
public ?exr
public ?exrs
public r?1?
public r?2?
public r?3?
public r?4?
public r?5?
?enr equ 0
?ensr equ 0
?exr equ 0
?exrs equ 0
r?1? equ 0
r?2? equ 0
r?3? equ 0
r?4? equ 0
r?5? equ 0
; +---------------------------------------------------------------------+
; | |
; | Wenn CRUNTIME als letztes Modul gebunden wird, hat end im Programm- |
; | lauf die Adresse hinter dem letzten Codebyte. |
; | |
; +---------------------------------------------------------------------+
public end?
end?:
end